(function() {

  // This would be the place to edit if you want a different
  // Base32 implementation

  var alphabet = '0123456789abcdefghjkmnpqrtuvwxyz'
  var alias = {
    o: 0,
    i: 1,
    l: 1,
    s: 5
  }

  /**
   * Build a lookup table and memoize it
   *
   * Return an object that maps a character to its
   * byte value.
   */

  var lookup = function() {
    var table = {}
      // Invert 'alphabet'
    for (var i = 0; i < alphabet.length; i++) {
      table[alphabet[i]] = i
    }
    // Splice in 'alias'
    for (var key in alias) {
      if (!alias.hasOwnProperty(key)) continue
      table[key] = table['' + alias[key]]
    }
    lookup = function() {
      return table
    }
    return table
  }

  /**
   * A streaming encoder
   *
   *     var encoder = new base32.Encoder()
   *     var output1 = encoder.update(input1)
   *     var output2 = encoder.update(input2)
   *     var lastoutput = encode.update(lastinput, true)
   */

  function Encoder() {
    var skip = 0 // how many bits we will skip from the first byte
    var bits = 0 // 5 high bits, carry from one byte to the next

    this.output = ''

    // Read one byte of input
    // Should not really be used except by "update"
    this.readByte = function(byte) {
      // coerce the byte to an int
      if (typeof byte == 'string') byte = byte.charCodeAt(0)

      if (skip < 0) { // we have a carry from the previous byte
        bits |= (byte >> (-skip))
      } else { // no carry
        bits = (byte << skip) & 248
      }

      if (skip > 3) {
        // not enough data to produce a character, get us another one
        skip -= 8
        return 1
      }

      if (skip < 4) {
        // produce a character
        this.output += alphabet[bits >> 3]
        skip += 5
      }

      return 0
    }

    // Flush any remaining bits left in the stream
    this.finish = function(check) {
      var output = this.output + (skip < 0 ? alphabet[bits >> 3] : '') + (check ? '$' : '')
      this.output = ''
      return output
    }
  }

  /**
   * Process additional input
   *
   * input: string of bytes to convert
   * flush: boolean, should we flush any trailing bits left
   *        in the stream
   * returns: a string of characters representing 'input' in base32
   */

  Encoder.prototype.update = function(input, flush) {
    for (var i = 0; i < input.length;) {
      i += this.readByte(input[i])
    }
    // consume all output
    var output = this.output
    this.output = ''
    if (flush) {
      output += this.finish()
    }
    return output
  }

  // Functions analogously to Encoder

  function Decoder() {
    var skip = 0 // how many bits we have from the previous character
    var byte = 0 // current byte we're producing

    this.output = ''

    // Consume a character from the stream, store
    // the output in this.output. As before, better
    // to use update().
    this.readChar = function(char) {
      if (typeof char != 'string') {
        if (typeof char == 'number') {
          char = String.fromCharCode(char)
        }
      }
      char = char.toLowerCase()
      var val = lookup()[char]
      if (typeof val == 'undefined') {
        // character does not exist in our lookup table
        return // skip silently. An alternative would be:
        // throw Error('Could not find character "' + char + '" in lookup table.')
      }
      val <<= 3 // move to the high bits
      byte |= val >>> skip
      skip += 5
      if (skip >= 8) {
        // we have enough to preduce output
        this.output += String.fromCharCode(byte)
        skip -= 8
        if (skip > 0) byte = (val << (5 - skip)) & 255
        else byte = 0
      }

    }

    this.finish = function(check) {
      var output = this.output + (skip < 0 ? alphabet[bits >> 3] : '') + (check ? '$' : '')
      this.output = ''
      return output
    }
  }

  Decoder.prototype.update = function(input, flush) {
    for (var i = 0; i < input.length; i++) {
      this.readChar(input[i])
    }
    var output = this.output
    this.output = ''
    if (flush) {
      output += this.finish()
    }
    return output
  }

  /** Convenience functions
   *
   * These are the ones to use if you just have a string and
   * want to convert it without dealing with streams and whatnot.
   */

  // String of data goes in, Base32-encoded string comes out.
  function encode(input) {
    var encoder = new Encoder()
    var output = encoder.update(input, true)
    return output
  }

  // Base32-encoded string goes in, decoded data comes out.
  function decode(input) {
    var decoder = new Decoder()
    var output = decoder.update(input, true)
    return output
  }

  /**
   * sha1 functions wrap the hash function from Node.js
   *
   * Several ways to use this:
   *
   *     var hash = base32.sha1('Hello World')
   *     base32.sha1(process.stdin, function (err, data) {
   *       if (err) return console.log("Something went wrong: " + err.message)
   *       console.log("Your SHA1: " + data)
   *     }
   *     base32.sha1.file('/my/file/path', console.log)
   */

  var crypto, fs

  var base32 = {
    Decoder: Decoder,
    Encoder: Encoder,
    encode: encode,
    decode: decode,
  }

  if (typeof window !== 'undefined') {
    // we're in a browser - OMG!
    window.base32 = base32
  }

  if (typeof module !== 'undefined' && module.exports) {
    // nodejs/browserify
    module.exports = base32
  }
})()
